﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace Gmantis.Controls.Chart
{
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public interface ICoordConverter
    {
        // Methods
        Point ConvertPoint(Point point);
        double ConvertX(double x);
        double ConvertY(double y);
        double ConvertZ(double z);

        // Properties
        Rect DataBounds { get; }
        Rect DataBounds2D { get; }
        Rect ViewBounds { get; }
    }

    [Flags]
    public enum SeriesDisplay : byte
    {
        HideLegend = 2,
        ShowNaNGap = 1,
        SkipNaN = 0
    }

    public class RenderContext
    {
        // Fields
        private Axis _ax;
        private Axis _ay;
        private Rect _bounds;
        private Rect _clipBounds;
        private Point _cur;
        private Point _curView;
        private Axis _defax;
        private Axis _defay;
        private IDataSeriesInfo _ds;
        private double[] _dvals;
        private bool _excludeHoles;
        private bool _isStacked;
        private string[] _names;
        private int _pi;
        private Point _prev;
        private List<Point> _pts;
        private Rect _rect;
        private IRenderer _rendrerer;
        private List<double> _stacked;
        internal Chart Chart;
        internal int ClusterPlotAreaIndex;
        internal bool hasNan;
        internal bool XReversed;
        internal bool YReversed;

        // Methods
        internal RenderContext()
        {
            this._cur = new Point();
            this._prev = new Point();
            this._curView = new Point();
            this._bounds = new Rect();
            this._stacked = new List<double>();
            this._excludeHoles = true;
            this._pts = new List<Point>();
            this._rect = Extensions.EmptyRect;
            this._clipBounds = Extensions.EmptyRect;
        }

        internal RenderContext(IRenderer renderer)
        {
            this._cur = new Point();
            this._prev = new Point();
            this._curView = new Point();
            this._bounds = new Rect();
            this._stacked = new List<double>();
            this._excludeHoles = true;
            this._pts = new List<Point>();
            this._rect = Extensions.EmptyRect;
            this._clipBounds = Extensions.EmptyRect;
            this._rendrerer = renderer;
        }

        internal RenderContext(IRenderer renderer, IDataSeriesInfo ds, int npts)
        {
            this._cur = new Point();
            this._prev = new Point();
            this._curView = new Point();
            this._bounds = new Rect();
            this._stacked = new List<double>();
            this._excludeHoles = true;
            this._pts = new List<Point>();
            this._rect = Extensions.EmptyRect;
            this._clipBounds = Extensions.EmptyRect;
            this._rendrerer = renderer;
            this._ds = ds;
            this._pts.Capacity = npts;
            if (this._ds != null)
            {
                this._names = this._ds.GetDataNames();
            }
            Chart visual = renderer.Visual as Chart;
            this.Chart = visual;
            BaseRenderer renderer2 = renderer as BaseRenderer;
            this._isStacked = (renderer2 != null) && renderer2.IsStacked;
            this.hasNan = renderer2._dataInfo.hasNaN;
            DataSeries series = ds as DataSeries;
            if (series != null)
            {
                Renderer2D rendererd = renderer as Renderer2D;
                if ((((byte)(series.Display & SeriesDisplay.ShowNaNGap)) != 0) && (rendererd != null))
                {
                    this._excludeHoles = false;
                }
                if (rendererd != null)
                {
                    string axisX = series.AxisX;
                    string axisY = series.AxisY;
                    bool flag = !string.IsNullOrEmpty(axisX);
                    bool flag2 = !string.IsNullOrEmpty(axisY);
                    if (visual != null)
                    {
                        ChartViewport2D viewElement = visual.ViewElement as ChartViewport2D;
                        if (viewElement != null)
                        {
                            if (flag || flag2)
                            {
                                foreach (Axis axis in viewElement.Axes)
                                {
                                    if (flag && (axis.AxisName == axisX))
                                    {
                                        this._ax = axis;
                                        this.hasNan = true;
                                    }
                                    if (flag2 && (axis.AxisName == axisY))
                                    {
                                        this._ay = axis;
                                        this.hasNan = true;
                                    }
                                }
                            }
                            this._defax = viewElement._ax;
                            this._defay = viewElement._ay;
                        }
                    }
                }
            }
            if (visual.View != null)
            {
                ChartView view = visual.View;
                if (this._ax != null)
                {
                    this.XReversed = this._ax.ReversedInternal;
                }
                else if (visual.View.AxisX != null)
                {
                    this.XReversed = visual.View.AxisX.Reversed;
                }
                if (this._ay != null)
                {
                    this.YReversed = this._ay.ReversedInternal;
                }
                else if (visual.View.AxisY != null)
                {
                    this.YReversed = visual.View.AxisY.Reversed;
                }
                Axis axis2 = visual.View.GetAxisX(series);
                if ((axis2 != null) && !double.IsNaN(axis2.LogBase))
                {
                    this.hasNan = true;
                }
                Axis axis3 = visual.View.GetAxisY(series);
                if ((axis3 != null) && !double.IsNaN(axis3.LogBase))
                {
                    this.hasNan = true;
                }
                if ((renderer2 != null) && renderer2.Inverted)
                {
                    if ((axis2 != null) && (axis2.PlotAreaIndex != 0))
                    {
                        this.ClusterPlotAreaIndex = axis2.PlotAreaIndex;
                    }
                }
                else if ((axis3 != null) && (axis3.PlotAreaIndex != 0))
                {
                    this.ClusterPlotAreaIndex = axis3.PlotAreaIndex;
                }
            }
        }

        private void CalcClipBounds()
        {
            this._clipBounds = new Rect(this.Bounds.X, this.Bounds.Y, this.Bounds2D.Width, this.Bounds2D.Height);
            Axis axis = this._ax;
            if (axis == null)
            {
                axis = this._defax;
            }
            if (axis != null)
            {
                Rect axisRect = axis.AxisRect;
                if (!axisRect.IsEmptyRect())
                {
                    this._clipBounds.X = axisRect.X;
                    this._clipBounds.Width = axisRect.Width;
                }
            }
            Axis axis2 = this._ay;
            if (axis2 == null)
            {
                axis2 = this._defay;
            }
            if (axis2 != null)
            {
                Rect rect = axis2.AxisRect;
                if (!rect.IsEmptyRect())
                {
                    this._clipBounds.Y = rect.Y;
                    this._clipBounds.Height = rect.Height;
                }
            }
        }

        public double ConvertX(double x)
        {
            if (this._ax != null)
            {
                return this._ax.ConvertEx(x);
            }
            if ((this._rendrerer != null) && (this._rendrerer.CoordConverter != null))
            {
                return this._rendrerer.CoordConverter.ConvertX(x);
            }
            return double.NaN;
        }

        public double ConvertY(double y)
        {
            if (this._ay != null)
            {
                return this._ay.ConvertEx(y);
            }
            if ((this._rendrerer != null) && (this._rendrerer.CoordConverter != null))
            {
                return this._rendrerer.CoordConverter.ConvertY(y);
            }
            return double.NaN;
        }

        internal double GetMaxX(Rect dataBounds)
        {
            if (this._ax != null)
            {
                return this._ax.Max0;
            }
            return dataBounds.Right;
        }

        internal double GetMaxY(Rect dataBounds)
        {
            if (this._ay != null)
            {
                return this._ay.Max0;
            }
            return dataBounds.Bottom;
        }

        internal double GetMinX(Rect dataBounds)
        {
            if (this._ax != null)
            {
                return this._ax.Min0;
            }
            return dataBounds.Left;
        }

        internal double GetMinY(Rect dataBounds)
        {
            if (this._ay != null)
            {
                return this._ay.Min0;
            }
            return dataBounds.Top;
        }

        internal void SetPoint(int pi, double x, double y)
        {
            this._pi = pi;
            this._dvals = null;
            Point item = new Point(x, y);
            this.Current = item;
            if (this._excludeHoles)
            {
                if (!double.IsNaN(x) && !double.IsNaN(y))
                {
                    this._pts.Add(item);
                }
            }
            else
            {
                if (!this.hasNan)
                {
                    this.hasNan = double.IsNaN(x) || double.IsNaN(y);
                }
                this._pts.Add(item);
            }
        }

        internal void SetPrevious(double value)
        {
            if (double.IsNaN(value))
            {
                value = 0.0;
            }
            this._stacked.Add(value);
        }

        // Properties
        public Rect Bounds
        {
            get
            {
                return this._bounds;
            }
            set
            {
                this._bounds = value;
                this.CalcClipBounds();
            }
        }

        internal Rect Bounds2D
        {
            get
            {
                return this._bounds;
            }
        }

        internal Rect ClipBounds
        {
            get
            {
                return this._clipBounds;
            }
        }

        public Point Current
        {
            get
            {
                return this._cur;
            }
            set
            {
                this._cur = value;
            }
        }

        public Point CurrentView
        {
            get
            {
                return this._curView;
            }
            set
            {
                this._curView = value;
            }
        }

        public double[] Data
        {
            get
            {
                if ((this._dvals == null) && (this._ds != null))
                {
                    double[,] values = this._ds.GetValues();
                    if (values != null)
                    {
                        int length = values.GetLength(1);
                        int pointIndex = this.PointIndex;
                        if ((pointIndex >= 0) && (pointIndex < length))
                        {
                            int num3 = values.GetLength(0);
                            this._dvals = new double[num3];
                            for (int i = 0; i < num3; i++)
                            {
                                this._dvals[i] = values[i, this.PointIndex];
                            }
                        }
                    }
                }
                return this._dvals;
            }
        }

        public IDataSeriesInfo DataSeries
        {
            get
            {
                return this._ds;
            }
            internal set
            {
                this._ds = value;
            }
        }

        internal bool IsCustomClipping
        {
            get
            {
                bool flag = false;
                if (this.Chart != null)
                {
                    switch (LineAreaOptions.GetClipping(this.Chart))
                    {
                        case Clipping.Auto:
                            {
                                BaseRenderer renderer = this._rendrerer as BaseRenderer;
                                if ((renderer != null) && (renderer.CoordConverter != null))
                                {
                                    Rect dataBounds = renderer.CoordConverter.DataBounds;
                                    Rect rc = new Rect(this.GetMinX(dataBounds), this.GetMinY(dataBounds), this.GetMaxX(dataBounds) - this.GetMinX(dataBounds), this.GetMaxY(dataBounds) - this.GetMinY(dataBounds));
                                    flag = renderer.IsCustomClipping(rc);
                                }
                                if (((this.Chart.VisualEffect == null) && (this.Chart.ChartType != ChartType.Polygon)) && (this.Chart.ChartType != ChartType.PolygonFilled))
                                {
                                    return flag;
                                }
                                return true;
                            }
                        case Clipping.Custom:
                            flag = true;
                            break;
                    }
                }
                return flag;
            }
        }

        public double this[string name]
        {
            get
            {
                double naN = double.NaN;
                if (this._names != null)
                {
                    double[] data = this.Data;
                    if (data == null)
                    {
                        return naN;
                    }
                    int length = this._names.Length;
                    for (int i = 0; i < length; i++)
                    {
                        if (name == this._names[i])
                        {
                            if (i < data.Length)
                            {
                                naN = data[i];
                            }
                            return naN;
                        }
                    }
                }
                return naN;
            }
        }

        internal double OptimizationRadius
        {
            get
            {
                DataSeries chart = this._ds as DataSeries;
                if (chart != null)
                {
                    double optimizationRadius = LineAreaOptions.GetOptimizationRadius(chart);
                    if (!double.IsNaN(optimizationRadius))
                    {
                        return optimizationRadius;
                    }
                }
                if (this.Chart != null)
                {
                    return LineAreaOptions.GetOptimizationRadius(this.Chart);
                }
                return double.NaN;
            }
        }

        internal OptimizationRadiusScope OptimizationRadiusScope
        {
            get
            {
                if (this.Chart != null)
                {
                    return LineAreaOptions.GetOptimizationRadiusScope(this.Chart);
                }
                return OptimizationRadiusScope.Lines;
            }
        }

        public int PointIndex
        {
            get
            {
                return this._pi;
            }
        }

        public Point[] Points
        {
            get
            {
                if (this._pts.Count <= 0)
                {
                    return null;
                }
                RadarRenderer renderer = this.Renderer as RadarRenderer;
                if ((renderer != null) && !renderer.IsPolar)
                {
                    this._pts.Add(this._pts[0]);
                }
                return this._pts.ToArray();
            }
        }

        public Point Previous
        {
            get
            {
                return this._prev;
            }
            set
            {
                this._prev = value;
            }
        }

        public double[] PreviousValues
        {
            get
            {
                if (this._stacked.Count > 0)
                {
                    return this._stacked.ToArray();
                }
                return null;
            }
        }

        public Rect Rect
        {
            get
            {
                return this._rect;
            }
            internal set
            {
                this._rect = value;
            }
        }

        public IRenderer Renderer
        {
            get
            {
                return this._rendrerer;
            }
        }
    }
}
